<HEAD>
  <SCRIPT SRC="../ganja.js"></SCRIPT>
</HEAD>
<BODY><SCRIPT>
// Create a Clifford Algebra with 3,0,1 metric.
Algebra(3,0,1,()=>{

  // The geometric elements of 3D PGA. 
  // Grade-1 elements (reflections) represent planes. 
  // Grade-2 elements (bireflections or line reflections) represent lines.
  // Grade-3 elements (trireflections or point reflections) represent points.
  var plane = (a,b,c,d)=>(a*1e1 + b*1e2 + c*1e3 + d*1e0).Normalized,
      line  = (...plucker)=>(plucker*[1e01,1e02,1e03,1e12,1e13,1e23]).Normalized,
      point = (x,y,z)=>!(1e0 + x*1e1 + y*1e2 + z*1e3);
      
  // Transformations in PGA are represented by versors, which
  // are compositions (geometric product) of reflections (vectors).
  
  // Both rotations and translations can be generated by exponentiating
  // the element they leave invariant. (the line you rotate around)
  var motor = (line,angle_or_distance)=>Math.E**(angle_or_distance/2 * line);
  
  // As in 2D finding transforms between elements only requires the square root.
  var sqrt = motor => ((Math.sign(motor.s) + motor)*(1 + 0.5*(motor.s + motor.Grade(4)))).Normalized;

  // motors can be interpolated (similar to quaternions in two ways).
  var lerp = (motor, x) => (Math.sign(motor().s)*(1-x) + x*motor).Normalized;

  // Create some points (P), lines (l), planes (p) to illustrate.
  var P1 = point(0,0,-1),       P2 = point(.3,0.4,-1),
      p1 = plane(0,1,0,0.2),    p2 = plane(-0.5,0.5,0,.5),
      l1 = line(0,0,.5,.1,1,0), l2 = line(0,0,.7,-.1,1,0);
      
  // Motors between all these elements :
  var P1toP2 = ()=>sqrt(P2 * P1),
      p1top2 = ()=>sqrt(p2 * p1),
      l1tol2 = ()=>sqrt(l2 * l1);
      
  // Graph it
  document.body.appendChild(this.graph(()=>{
    // Animation time.
    var t = 0.5+0.5*Math.sin(performance.now()/1000);

    // A rotation around the z-axis.
    var R = motor(line(0,0,0,1,0,0),t*Math.PI*2);
    
    return [
      "Rotations and Translations",
      0x882288,lerp(p1top2, t) >>> p1*0.3,     // move between planes
      0x882288,lerp(l1tol2,t) >>> l1,          // move between lines
      0x882288,lerp(P1toP2,t) >>> P1,          // move between points.
      0x224488,[P1,R >>> P2],"R",              // R applied to P2
      0x008844,P1,"P1",P2,"P2",                // our two points.   
      0x008844,p1*0.3,"p1",p2*0.3,"p2",        // our two planes.
      0x228844,l1,"l1",l2,"l2",                // our two lines.
    ];
  },{grid:true, labels:true,lineWidth:3, h:-0.4, p:-0.1, scale:1.4, animate:true}));

});
</SCRIPT></BODY>